home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / util / snap_1_4 / part04 < prev   
Encoding:
Internet Message Format  |  1990-02-11  |  54.5 KB

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i070: Snap 1.4 - cut, store, and paste between windows, Part04/04
  5. Message-ID: <11378@xanth.cs.odu.edu>
  6. Date: 11 Feb 90 22:52:14 GMT
  7. Sender: tadguy@cs.odu.edu
  8. Reply-To: micke@slaka.sirius.se (Mikael Karlsson)
  9. Lines: 1558
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11. X-Mail-Submissions-To: Amiga@cs.odu.edu
  12. X-Post-Discussions-To: comp.sys.amiga
  13.  
  14. Submitted-by: micke@slaka.sirius.se (Mikael Karlsson)
  15. Posting-number: Volume 90, Issue 070
  16. Archive-name: util/snap-1.4/part04
  17.  
  18. #!/bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 4 (of 4)."
  25. # Contents:  snap.doc source/snap.c
  26. # Wrapped by tadguy@xanth on Sun Feb 11 17:48:49 1990
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'snap.doc' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'snap.doc'\"
  30. else
  31. echo shar: Extracting \"'snap.doc'\" \(22295 characters\)
  32. sed "s/^X//" >'snap.doc' <<'END_OF_FILE'
  33. X                     Snap 1.4
  34. X                     ========
  35. X               (c) Mikael Karlsson 1989
  36. X      Keymap inverting courtesy of Jim Mackraz
  37. X
  38. X
  39. XIs it Public Domain?
  40. X
  41. X  Snap is NOT Public Domain. Snap is 'Freely distributable
  42. X  copyrighted software with a shareware option'.
  43. X
  44. X  "Permission is hereby granted to copy Snap provided that
  45. X   the copyright notice and this document is left intact.
  46. X   Copies may not be made for profit."
  47. X
  48. X  I don't know if the above should hold in court but what
  49. X  I mean is: Copy Snap if you want to but don't make a
  50. X  business of it. It is of course free to include it on
  51. X  public domain disks or putting it on a BBS.
  52. X  If you find Snap useful, please feel free to send a
  53. X  donation ($10 is a nice round number) or a nice program (PD).
  54. X  Or you can buy me a beer or two when we meet.
  55. X  If you wish to include Snap with a commercial product,
  56. X  please contact me first. I just want to make sure that
  57. X  my ego can stand for it. Of course it would also be nice
  58. X  with a registred copy of the product.
  59. X  (How about including it with a '030 card? ;-)
  60. X
  61. X  Also read this message that Jim Mackraz sent to me regarding
  62. X  some code used in Snap:
  63. X
  64. X  "You may use ikm.c in your product Snap.
  65. X   You may not distribute the source to ikm.c for profit,
  66. X   and any distribution of ikm.c must retain the original
  67. X   copyright message.
  68. X
  69. X   You should also be warned that IKM() has not been
  70. X   substantially verified in either design or implementation,
  71. X   and that it will be made obsolete in version V1.4 by a
  72. X   new OS function call.
  73. X
  74. X   There is no explicit or implied guarantee that ikm.c contains
  75. X   only supported algorithms.  It may have problems in a future
  76. X   release of the system.
  77. X
  78. X      jimm
  79. X
  80. X   Jim Mackraz
  81. X   Aug 18, 1989"
  82. X
  83. X
  84. XWhat is it?
  85. X
  86. X  Snap is the perfect tool for the lazy typer. Isn't it
  87. X  irritating when you look at something on the screen
  88. X  and think: "That is what I'm going to type."?
  89. X  What if you could just point at it and get the computer to
  90. X  type it for you? That's where Snap comes to the rescue.
  91. X  Another thing that irritates me is that I'm sitting in
  92. X  front of THE computer and still I must have pen and
  93. X  paper available to scribble down something from the screen
  94. X  that I know I will need later. Snap provides a solution
  95. X  to that problem also. Just frame it and Snap creates a
  96. X  window with a copy of the screen contents. Perfect for
  97. X  snapping text from later on. This is another idea borrowed
  98. X  from the computer scientists at Xerox Palo Alto Research
  99. X  Center (you know, the ones who invented the mouse, windows,
  100. X  icons and stuff like that).
  101. X
  102. X
  103. XWhy use Snap instead?
  104. X
  105. X   a. Snap finds out the character coordinates automatically.
  106. X   b. Snap uses the RastPort's current font, not just Topaz 8.
  107. X   c. Snap was written by me.
  108. X   d. Snap supports all fixed width fonts with width and height<16.
  109. X   e. Snap supports accented characters (128-255).
  110. X   f. Snap supports keymaps, thanks to Jim Mackraz.
  111. X   g. Snap does both column and text oriented snapping.
  112. X   h. Snap snaps graphics.
  113. X   i. Snap uses the clipboard, making it compatible with TxED (and NotePad).
  114. X   j. Snap understands inverted characters.
  115. X   k. Snap understands bold characters.
  116. X   l. Snap understands underlined characters
  117. X   m. Snap does word oriented snapping.
  118. X   n. Snap has ants.
  119. X   o. Snap has a key combination to do insert.
  120. X   p. Snap supports Xerox style snapping with immediate insert.
  121. X   q. Snap prepends and appends characters.
  122. X   r. Snap saves graphics.
  123. X   s. Snap caches the character offsets between windows.
  124. X   t. Snap joins long lines.
  125. X   u. Snap supports ARexx to read and set prepend and append strings.
  126. X   v. Snap handles an extra pixel line between character rows.
  127. X
  128. X
  129. XStarting and Stopping
  130. X
  131. X   Start Snap with 'snap'. That's it. Snap detaches itself
  132. X   from the CLI, making it possible to close the CLI.
  133. X   Make sure that you have 'clipboard.device' in devs:.
  134. X   To get rid of Snap, execute 'snap -Q' (or snap QUIT).
  135. X   Note that you can't remove Snap if you have any 'snapped'
  136. X   windows left.
  137. X
  138. X
  139. XCommand line arguments
  140. X
  141. X   Snap accepts a couple of command line arguments. You can
  142. X   use either unix or Amiga style arguments.
  143. X   XX is hex. NN is decimal. str is a string.
  144. X
  145. X   Usage:
  146. X    snap -pNN -tXX -gXX -iXX -wXX -Pstr -Astr -cNN -lNN -aXXXX
  147. X      -x -X -e -E -r -R -j -J -uN -bXX -oNN -CNN -BNN -Q
  148. X    or
  149. X    snap PRIORITY/k TEXTQUAL/k GFXQUAL/k INSERTKEY/k CWKEY/k
  150. X      PREPEND/k APPEND/k CHARDELAY/k LINEDELAY/k CRAWLPTRN/k
  151. X      XEROX/s NOXEROX/s EARLYPATCH/s NOEARLYPATCH/s STARTUNIT/k
  152. X      TRUEUNDERSCORE/k FAKEUNDERSCORE/s JOINLONG/s NOJOINLONG/s
  153. X      PLANEMASK/k GADOFFSET/k CACHESIZE/k BADCHAR/s QUIT/s
  154. X
  155. X    -pNN
  156. X    PRIORITY NN
  157. X            where NN is the priority to use when installing
  158. X            the input handler. Default is 51. Note that it's
  159. X            not possible to change the priority of the input
  160. X            handler while Snap is running.
  161. X    -tXX
  162. X    TEXTQUAL XX
  163. X            where XX is the text qualifier to use in text
  164. X            operations. Default is the left Amiga key.
  165. X    -gXX
  166. X    GFXQUAL XX
  167. X            where XX is the graphics qualifier to use in
  168. X            graphics operations. Default is the right Amiga key.
  169. X    -iXX
  170. X    INSERTKEY XX
  171. X            where XX is the raw key code for the key to be used
  172. X            together with the left Amiga key as insert key.
  173. X            Use together with Shift to get modidified inserts.
  174. X            Use 0 to disable. Default is hex 17 ("I").
  175. X    -wXX
  176. X    CWKEY XX
  177. X            where XX is the raw key code for the key to be used
  178. X            together with the left Amiga key to open the Snap
  179. X            control window. Default is hex 11 ("W").
  180. X    -Pstr
  181. X    PREPEND str
  182. X            where str is the string that will be inserted in
  183. X            front of every line in a modified insert. Max
  184. X            length of the string is 16. Default is "> ".
  185. X    -Astr
  186. X    APPEND str
  187. X            where str is the string that will be inserted after
  188. X            every line in a modified insert. Max length of the
  189. X            string is 16. Default is "".
  190. X    -cNN
  191. X    CHARDELAY NN
  192. X            where NN is the amount of time that Snap should
  193. X            wait after each character inserted into the input
  194. X            stream. Default is 0.
  195. X    -lNN
  196. X    LINEDELAY NN
  197. X            where NN is the amount of time that Snap should
  198. X            wait after each carriage return inserted into the
  199. X            input stream. Default is 0.
  200. X    -aXXXX
  201. X    CRAWLPTRN XXXX
  202. X            where XXXX is a 16 bit number that specifies the
  203. X            pattern for the crawling ants. Use FFFF to turn
  204. X            the crawling off. If you specify 0 as the crawl
  205. X            pattern, Snap will use different patterns for
  206. X            each snapping mode (box/char/word/line).
  207. X            Default is 7777.
  208. X    -x
  209. X    XEROX
  210. X            tells Snap to use Xerox style snapping instead.
  211. X            The snapped text is inserted immediately it has
  212. X            been snapped.
  213. X    -X
  214. X    NOXEROX
  215. X            turns off Xerox style snapping.
  216. X    -e
  217. X    EARLYPATCH
  218. X            tells Snap to patch dangerous functions as soon as
  219. X            the text qualifier goes down. This is done automatically
  220. X            when you use Xerox style snapping.
  221. X    -E
  222. X    NOEARLYPATCH
  223. X            turns off early patching. This is default.
  224. X    -j
  225. X    JOINLONG
  226. X            tells Snap to join long lines. This means that Snap
  227. X            joins (removes the line feed between) two lines if
  228. X            the first line has a non-blank in the last position.
  229. X            This is not done in rectangular snapping.
  230. X    -J
  231. X    NOJOINLONG
  232. X            disables the join-long-lines behavior. This is default.
  233. X    -uN
  234. X    STARTUNIT N
  235. X            tells Snap which unit to use when you start snapping.
  236. X            0 is rectangular snapping (FRAME).
  237. X            1 is character snapping (CHAR). Default is 0.
  238. X    -r
  239. X    TRUEUNDERSCORE
  240. X            tells Snap to do true checking of underscores when
  241. X            snapping characters.
  242. X    -R
  243. X    FAKEUNDERSCORE
  244. X            turns off true checking of underscores. Instead Snap
  245. X            just skips the underscore line and hopes that the rest
  246. X            of the character will provide correct matching. This
  247. X            option is provided since there is a bug in the rendering
  248. X            of underscored characters.
  249. X    -bXX
  250. X    PLANEMASK XX
  251. X            where XX is the bit plane mask used when drawing the
  252. X            selection frame for character snapping. This does not
  253. X            affect graphics snapping. Default is 1.
  254. X    -oNN
  255. X    GADOFFSET NN
  256. X            where NN is the offset for the save gadget. This may
  257. X            be necessary to use if you use some kind of iconifier
  258. X            program that puts a gadget where Snap usually puts the
  259. X            save gadget. Default is 52.
  260. X    -CNN
  261. X    CACHESIZE NN
  262. X            where NN is the number of windows that Snap will cache
  263. X            character offsets for. Specifying a new value while Snap
  264. X            is running means that you increase the cache size by N.
  265. X            Default size is 10, default increase is 0.
  266. X    -BNN
  267. X    BADCHAR NN
  268. X            where NN is the ascii value of the character that will
  269. X            be used when Snap doesn't recognize a character.
  270. X            Default is 63, a '?'.
  271. X    -Q
  272. X    QUIT
  273. X            removes Snap.
  274. X
  275. XQUALIFIERS (always entered in HEX)  (This list borrowed from Matt Dillon)
  276. X
  277. X    0001    Left Shift
  278. X    0002    Right Shift
  279. X    0004    Caps Lock
  280. X    0008    Control
  281. X    0010    Left Alt
  282. X    0020    Right Alt
  283. X    0040    Left Amiga Key
  284. X    0080    Right Amiga Key
  285. X    0100    Numeric Key Pad Key (not useful)
  286. X    0200    Repeat              (not useful)
  287. X    0400    Interrupt           (not useful)
  288. X    0800    Multibroadcast      (not useful)
  289. X    1000    Middle Mouse Button (not normally implemented by intuition)
  290. X    2000    Right Mouse Button
  291. X    4000    Left Mouse Button
  292. X
  293. X    Note: Combinations are allowed, in which case any one of the
  294. X          elected qualifiers along with the left, right mouse button
  295. X          will cause the appropriate action to occur.
  296. X
  297. X   Some useful raw key codes:
  298. X    17 I    seems to become the Amiga standard
  299. X    34 V    for you Macintosh freaks
  300. X    15 Y    good ol' Emacs
  301. X
  302. X
  303. XModified inserts
  304. X
  305. X   Modified insert means that extra characters are added in front of
  306. X   and after each line as it is inserted. The characters in front
  307. X   are set via the -P/PREPEND command line argument, the characters
  308. X   after via the -A/APPEND command line argument.
  309. X   These strings can also be set from ARexx using the commands
  310. X   'PREPEND newstring' and
  311. X   'APPEND newstring'.
  312. X   These commands should be addressed to Snap using the ARexx command
  313. X   'ADDRESS SNAP'.
  314. X   The old string is returned in the RESULT variable, provided that
  315. X   'OPTIONS RESULTS' is given.
  316. X   If no newstring is given then no change is made.
  317. X   A small example:
  318. X
  319. X    /* Change PREPEND and APPEND strings for my mail answering program */
  320. X
  321. X    PARSE ARG ReplyTo
  322. X
  323. X    OPTIONS RESULTS
  324. X
  325. X    ADDRESS SNAP 'prepend' ReplyTo'>'
  326. X    oldprepend = RESULT
  327. X    ADDRESS SNAP 'append' ""
  328. X    oldappend = RESULT
  329. X
  330. X
  331. XDelays
  332. X
  333. X   The character and line delay may be necessary with some programs
  334. X   that can't handle the amount of characters the Snap insert into
  335. X   the input stream. CygnusEd is known to have problems with this.
  336. X   TxED and UEdit handles inserted characters very nicely.
  337. X   The delay is specified in milliseconds, eg a value of 1000 gives
  338. X   a delay of 1 second.
  339. X
  340. X
  341. XWatch out for
  342. X
  343. X   The Early Patch behavior may cause problems if you use the Left
  344. X   Amiga key as the text qualifier together with MachII. What
  345. X   happens is that MachII can't activate a new window when you do
  346. X   a Left Amiga-M.
  347. X   Underscored characters can give problems. Apart from the bug
  348. X   mentioned above there's another problem. In some fonts the
  349. X   underscore character (_) and an underscored space looks the
  350. X   same. Snap tries to be smart and usually gets it right. The
  351. X   algorithm used is the following:
  352. X   An underscore/underscored space is interpreted as an underscored
  353. X   space if the previous character was underscored, otherwise it's
  354. X   interpreted as a true underscore character.
  355. X
  356. X
  357. XSnapping
  358. X
  359. X   Snapping comes in two flavors; characters and graphics.
  360. X   Snapping graphics simply means that you can frame an
  361. X   area on screen and that area is copied into a window.
  362. X   Character snapping can be made in four different ways:
  363. X   * rectangular snapping
  364. X   * character oriented snapping
  365. X   * word oriented snapping
  366. X   * line oriented snapping
  367. X
  368. X   Rectangular snapping makes it possible to snap a column
  369. X   of text. A carriage return is inserted after each row,
  370. X   except the last one.
  371. X
  372. X   Line oriented snapping is much the same as rectangular
  373. X   snapping, except that the width of the rectangle is the
  374. X   width of the window.
  375. X
  376. X   Character oriented snapping is much harder to explain than
  377. X   to use. Character oriented snapping starts at one character,
  378. X   extends to the right edge of the window, goes on with
  379. X   complete lines, and ends at another character. The select box
  380. X   can look like this: ________________________
  381. X    __________________|                        |
  382. X   |                                           |
  383. X   |                 __________________________|
  384. X   |________________|
  385. X
  386. X   or like this:                      _________
  387. X    _____                            |_________|
  388. X   |_____|
  389. X
  390. X   and of course like this:    ________________
  391. X                              |________________|
  392. X
  393. X   Word oriented snapping works the same way as character
  394. X   oriented, except that you can only extend the selection
  395. X   word by word. A word is defined as non-blanks surrounded
  396. X   by blanks.
  397. X
  398. X
  399. X   Let's define some actions used when controlling snap.
  400. X
  401. X   CLICK
  402. X      1. Press the mouse button.
  403. X      2. Release the mouse button.
  404. X
  405. X   MOVE
  406. X      1. Move the mouse.
  407. X
  408. X   PREPARE_TEXT
  409. X      1. If you are using Xerox style snapping, make sure that your
  410. X         intended destination window is active.
  411. X      2. Press and hold the text qualifier (Default: Left Amiga key).
  412. X      3. MOVE to the first character you want to copy.
  413. X
  414. X   PREPARE_GFX
  415. X      1. Press and hold the graphics qualifier (Default: Right Amiga key).
  416. X      2. MOVE to the upper left corner of the area you want to copy
  417. X
  418. X   EXTEND
  419. X      1. MOVE
  420. X      5. (Press and) Release the mouse button.
  421. X
  422. X   END
  423. X      1. Release the mouse button.
  424. X      2. Release the qualifier.
  425. X
  426. X   CANCEL
  427. X      1. Release the qualifier.
  428. X      2. Release the mouse button.
  429. X
  430. X
  431. X   Ways to use these actions:
  432. X   This is with starting unit FRAME. Selecting starting unit CHAR will
  433. X   skip rectangular snapping and take you directly to character oriented
  434. X   snapping. To do rectangular snapping you have to click through char,
  435. X   word and line oriented back to rectangular snapping.
  436. X
  437. X   To do rectangular snapping:
  438. X    1. PREPARE_TEXT.
  439. X    2. Press the left mouse button.
  440. X    3. MOVE.
  441. X    4. EXTEND until satisfied.
  442. X    5. END or CANCEL.
  443. X
  444. X   To do character oriented snapping
  445. X    1. PREPARE_TEXT.
  446. X    2. CLICK the left mouse button.
  447. X    3. EXTEND until satisfied.
  448. X    4. END or CANCEL.
  449. X
  450. X   To do word oriented snapping
  451. X    1. PREPARE_TEXT.
  452. X    2. Double-CLICK left mouse button.
  453. X    3. EXTEND until satisfied.
  454. X    4. END or CANCEL.
  455. X
  456. X   To do line oriented snapping
  457. X    1. PREPARE_TEXT.
  458. X    2. Triple-CLICK left mouse button.
  459. X    3. EXTEND until satisfied.
  460. X    4. END or CANCEL.
  461. X
  462. X   To insert snapped characters (BKSYSBUF "You know ;-)")
  463. X    1. PREPARE_TEXT.
  464. X    2. CLICK the right mouse button.
  465. X   or
  466. X    1. Press and hold the left amiga key.
  467. X    2. Type the insert key as specified with -i (Default "I").
  468. X
  469. X   To insert snapped characters including prepend and append strings
  470. X    1. Press and hold the left amiga key and either shift key.
  471. X    2. Type the insert key as specified with -i (Default "I").
  472. X
  473. X   To abort insertion
  474. X    1. CLICK the left mouse button.
  475. X
  476. X   To snap graphics
  477. X    1. PREPARE_GFX.
  478. X    2. Press the left mouse button.
  479. X    3. MOVE.
  480. X    4. EXTEND until satisfied.
  481. X    5. END or CANCEL.
  482. X
  483. X   To open the Snap Control Window
  484. X    1. Press and hold the left amiga key.
  485. X    2. Type the control window key as specified with -w (Default "W").
  486. X
  487. X   When snapping text you can go directly from snapping to
  488. X   inserting by replacing "END or CANCEL" above with
  489. X   "Release left mouse button - CLICK right mouse button".
  490. X   If you are using Xerox style snapping, the snapped text
  491. X   will be inserted as soon as you END.
  492. X   When selecting snapping unit a fourth click takes you
  493. X   back to character oriented snapping. Each click steps
  494. X   one unit. Note that rectangular snapping only is available
  495. X   if you MOVE before you release the mouse button.
  496. X
  497. X
  498. XSnapping characters, character coordinates and caching
  499. X
  500. X   You must always start snapping at a character, otherwise
  501. X   Snap won't get the coordinates right. This applies to all
  502. X   kinds of snapping including line snapping.
  503. X   Snap caches the character coordinates for the N last used
  504. X   windows, where N is specified by the -C/CACHESIZE parameter.
  505. X   When you start snapping in a window Snap checks it's cache
  506. X   to see whether you have snapped in this window before.
  507. X   If the window is in the cache then Snap first tries to find
  508. X   a character at the previous coordinates. If no character is
  509. X   found at the cached coordinates then Snap goes through the
  510. X   complete lookup process. Of course this is transparent to
  511. X   the user, so you don't have to worry about it. The size of
  512. X   the cache can be specified by the user and is managed on a
  513. X   Least Recently Used basis.
  514. X   The caching makes it possible for Snap to get the correct
  515. X   character coordinates even if you start snapping on a space,
  516. X   provided that you've snapped in that window before.
  517. X
  518. X   Trailing blanks are removed on each line when you're snapping
  519. X   characters, words or lines, but not when doing rectangular
  520. X   snapping. Trailing blanks are only removed in line mode if
  521. X   you're snapping a single line.
  522. X
  523. X
  524. XSnapping and Saving Graphics
  525. X
  526. X   Windows with graphic snaps are always opened on the Workbench
  527. X   screen. If you've snapped graphics from a screen with different
  528. X   colors then you can switch to the graphic snap's original colors
  529. X   by holding down the left mouse button inside the snap window.
  530. X   Saving of graphics is done via the Snap Control Window (SCW).
  531. X   To the left of a Snap window's window-to-front and window-to-back
  532. X   gadgets is a small gadget that looks like a disk. Clicking this
  533. X   disk gadget has different effects according to a two conditions.
  534. X
  535. X     SCW        Graphics Window
  536. X   not open      not selected     Opens the SCW, selects the Graphics Window
  537. X     open        not selected     Selects the Graphics Window.
  538. X     open          selected       Saves the contents of the Graphics Window
  539. X
  540. X   The Snap Control Window looks something like this:
  541. X    _______________________________
  542. X   |x|Snap_Control_Window________|||
  543. X   | ____      __________________  |
  544. X   ||Save| as |Name gadget       | |
  545. X   | ~~~~      ~~~~~~~~~~~~~~~~~~  |
  546. X   | Transparent color |0~~|       |
  547. X   |                    ~~~        |
  548. X    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  549. X   The Save gadget will be ghosted if no window is selected.
  550. X   Clicking the Save gadget will save the contents of the
  551. X   selected Graphics Window as an IFF file.
  552. X   The Transparent color gadget is used to specify which color
  553. X   will be transparent in the saved IFF file.
  554. X   The Name gadget is used to specify the name of the IFF file
  555. X   to save. The Name gadget is a string gadget if arp.library
  556. X   isn't available. If arp.library is available it will be a
  557. X   click-gadget that brings up an Arp File Requester.
  558. X
  559. X
  560. XCompiling
  561. X
  562. X   A 'makefile' is provided. Depending on which compiler you
  563. X   use, remove and insert '#'s.
  564. X   I seem to have some problem with the detaching when using
  565. X   Lattice. Everything works ok, except that you can't close
  566. X   the CLI-window. If anybody solves it, I'd be very grateful
  567. X   to know about it.
  568. X
  569. X
  570. XSome things to remember
  571. X
  572. X   a. The text is sent to the active window. Make sure that
  573. X      the correct window is active.
  574. X   b. Don't interfere when the text is being inserted. Any key
  575. X      pressed by you will be inserted in the middle of the text
  576. X      being inserted.
  577. X   c. Snap begins with an attempt to find the character coordinates.
  578. X      Therefore if you begin snapping on a space, Snap will almost
  579. X      certainly get the wrong coordinates, unless Snap has cached
  580. X      the character coordinates from a previous snap.
  581. X   d. To be able to do Xerox style snapping, Snap disables
  582. X      ActivateWindow when the text qualifier is held down.
  583. X      By doing this Snap makes sure that the destination window
  584. X      remains active when you move out of it, even if you are
  585. X      using DMouse or another Sun mouse utility.
  586. X
  587. X
  588. XBugs
  589. X
  590. X   Of course, what did you think. Well, as far as I know there
  591. X   are no explicit bugs. Oh yes, there is one that I don't know
  592. X   how to solve. The problem is that some font editors optimize
  593. X   the character image data. The result is that two characters
  594. X   with the same image (e.g. I and l in some fonts) uses the
  595. X   same image data, thereby making it impossible for Snap to
  596. X   determine which character was printed in the first place.
  597. X   This can be solved by editing the font so that each character
  598. X   is unique.
  599. X
  600. X
  601. XAcknowledgements
  602. X
  603. X   Thanks to:
  604. X
  605. X   o Amiga-Lorraine for the machine.
  606. X   o Jim Mackraz for the keymap inverting code.
  607. X   o Radical Eye Software for "minrexx".
  608. X   o William Hawes for ARexx, WShell, ConMan, etc.
  609. X   o Bjorn Knutsson, Dominic Giampal, Marc Boucher, Eddy Carroll
  610. X     and Jonas Petersson for testing.
  611. X   o All of you who has sent or will send comments, contributions
  612. X     or questions.
  613. X
  614. XImprovements
  615. X
  616. X   I've been thinking about adding a way for programs to "register"
  617. X   their windows with Snap so that Snap can let the program handle
  618. X   the snapping by itself. As an example: Snapping an icon as text
  619. X   doesn't make much sense, so the program displaying the icon
  620. X   could take over and put the name of the file in the clipboard.
  621. X   A character-mapped window could also benefit from this.
  622. X
  623. X
  624. Xs-mail: Mikael Karlsson
  625. X        Lovsattersvagen 10
  626. X        S-585 98  LINKOPING
  627. X        SWEDEN
  628. X
  629. Xe-mail: micke@slaka.sirius.se
  630. X        micke@slaka.UUCP
  631. X        {mcvax|munnari|seismo}!sunic!liuida!slaka!micke
  632. X
  633. XPhone:  +46-13 50479
  634. X        +46-431 50623 (in the summer)
  635. END_OF_FILE
  636. if test 22295 -ne `wc -c <'snap.doc'`; then
  637.     echo shar: \"'snap.doc'\" unpacked with wrong size!
  638. fi
  639. # end of 'snap.doc'
  640. fi
  641. if test -f 'source/snap.c' -a "${1}" != "-c" ; then 
  642.   echo shar: Will not clobber existing file \"'source/snap.c'\"
  643. else
  644. echo shar: Extracting \"'source/snap.c'\" \(29507 characters\)
  645. sed "s/^X//" >'source/snap.c' <<'END_OF_FILE'
  646. X/***********************************************\
  647. X*                                               *
  648. X*                     Snap                      *
  649. X*           (c) Mikael Karlsson 1988              *
  650. X*                                               *
  651. X\***********************************************/
  652. X/* Auto: make
  653. X*/
  654. X
  655. X#ifdef SNAPREXX
  656. X#include "minrexx.h"
  657. X#endif
  658. X
  659. X#define ARGVAL() (*++(*argv) || (--argc && *++argv))
  660. X
  661. X/* signals */
  662. XLONGBITS startsignal, insertsignal, cancelsignal, donesignal;
  663. XLONGBITS movesignal, clicksignal, timersignal, initsignal, cwsignal;
  664. XULONG startsignum = -1L;
  665. XULONG insertsignum = -1L;
  666. XULONG cancelsignum = -1L;
  667. XULONG donesignum = -1L;
  668. XULONG movesignum = -1L;
  669. XULONG clicksignum = -1L;
  670. XULONG timersignum = -1L;
  671. XULONG initsignum = -1L;
  672. XULONG cwsignum = -1L;
  673. XULONG WaitSignal;
  674. X
  675. X/* program */
  676. Xstruct SnapRsrc *SnapRsrc = NULL;
  677. Xstruct Task *MyTask;
  678. X
  679. X/* Snap state machine */
  680. XWORD action;
  681. XWORD state;
  682. X
  683. X/* clipboard */
  684. Xstruct IOClipReq *ClipReq = NULL;
  685. Xstruct MsgPort *ClipPort = NULL;
  686. X
  687. X/* timer device */
  688. Xstruct MsgPort *TimerPort = NULL;
  689. Xstruct timerequest MyTR;
  690. X
  691. X/* input device */
  692. Xstruct MsgPort *inputDevPort = NULL;
  693. Xstruct Interrupt handlerStuff;
  694. Xstruct IOStdReq *inputRequestBlock = NULL;
  695. Xstruct InputEvent SimEvent;
  696. XWORD textqual;
  697. XWORD gfxqual;
  698. XWORD insertkey;
  699. XWORD cwkey;
  700. XWORD modinsert;
  701. X
  702. XUBYTE *CharData = NULL;
  703. XUBYTE TrueUnderscore;
  704. X
  705. X/* console */
  706. Xstruct MsgPort *ConPort = NULL;
  707. Xstruct IOStdReq *ConIOR = NULL;
  708. Xstruct KeyMap keymap;
  709. X
  710. X/* windows */
  711. Xstruct MsgPort *Sharedport = NULL;
  712. XSHORT Sharedrefs;
  713. XIMPORT UBYTE *WindowTitle;
  714. XIMPORT struct Window *ControlWindow;
  715. Xstruct Window *SaveWin = NULL;
  716. XIMPORT struct Gadget SaveGad;
  717. XIMPORT struct Gadget NameGad;
  718. Xstruct GfxSnap *SwapGS = NULL;
  719. Xstruct MinList CachedWindows;
  720. XIMPORT struct StringInfo TranspSI;
  721. X
  722. X/* libraries */
  723. Xstruct IntuitionBase *IntuitionBase = NULL;
  724. Xstruct GfxBase       *GfxBase = NULL;
  725. Xstruct LayersBase    *LayersBase = NULL;
  726. Xstruct ArpBase       *ArpBase = NULL;
  727. X/* struct DosLibrary    *DosBase = NULL; */
  728. X
  729. X/* graphics */
  730. Xstruct Screen *theScreen;
  731. Xstruct Layer *theLayer;
  732. Xstruct RastPort rp, TempRp, MyRP;
  733. Xstruct BitMap TempBM, MyBM;
  734. XUBYTE *TempRaster = NULL;
  735. X
  736. XIMPORT struct FileRequester NameFR;
  737. XIMPORT UBYTE SaveName[256];
  738. XIMPORT UBYTE SaveDirName[256];
  739. XBPTR SnapFile;
  740. X
  741. X/* ARexx stuff */
  742. X#ifdef SNAPREXX
  743. XULONG rexxsignal;
  744. XIMPORT struct rexxCommandList rcl[];
  745. XWORD disp();
  746. X#endif
  747. X
  748. X/* detaching */
  749. XULONG _BackGroundIO = 0;
  750. XULONG _stack = 4096L;
  751. XULONG _priority = 4L;
  752. Xchar *_procname = "Snap";
  753. X#ifdef LATTICE
  754. Xextern BPTR _Backstdout;
  755. X#endif LATTICE
  756. X
  757. XWORD isdigit(c)
  758. XREGISTER char c;
  759. X{
  760. X    return (WORD)(c>='0' && c<='9');
  761. X}
  762. X
  763. X#ifdef AZTEC_C
  764. Xchar *strupr(str)
  765. Xchar *str;
  766. X{
  767. X    register char *p = str;
  768. X    register char c;
  769. X    while (c = *p) {
  770. X        if ('a' <= c && c <= 'z') {
  771. X            *p = c - ('a' - 'A');
  772. X        }
  773. X        ++p;
  774. X    }
  775. X    return str;
  776. X}
  777. X#endif AZTEC_C
  778. X
  779. XLONG dectoint(str)
  780. XREGISTER char *str;
  781. X{
  782. X    REGISTER long val = 0;
  783. X    REGISTER char c;
  784. X    while (isdigit(c = *str)) {
  785. X        val = (((val<<2)+val)<<1) + c-'0';
  786. X        str++;
  787. X    }
  788. X    return(val);
  789. X}
  790. X
  791. XLONG hextoint(str)
  792. XREGISTER char *str;
  793. X{
  794. X    REGISTER long val = 0;
  795. X    REGISTER char c;
  796. X    while (c = *str) {
  797. X        val <<= 4;
  798. X        val |= (c & 15) + (isdigit(c) ? 0 : 9);
  799. X        str++;
  800. X    }
  801. X    return(val);
  802. X}
  803. X
  804. XWORD insertcount;
  805. X
  806. XVOID InsertAscii(ascii)
  807. XULONG ascii;
  808. X{
  809. X    if (insertcount == 1) {   /* Time for second char */
  810. X          /* Not necessary to patch here but it guarantees
  811. X             that all inserted chars end up in the same window. */
  812. X        SafePatch();
  813. X    }
  814. X    InvertKeyMap(ascii, &SimEvent, &keymap);
  815. X    DoIO(inputRequestBlock);
  816. X    if (SnapRsrc->chardelay) {
  817. X        MyTR.tr_node.io_Command = TR_ADDREQUEST;
  818. X        MyTR.tr_time.tv_micro = SnapRsrc->chardelay;
  819. X        MyTR.tr_time.tv_secs = 0;
  820. X        DoIO((struct IOStdReq *)&MyTR);
  821. X    }
  822. X    ++insertcount;
  823. X}
  824. X
  825. XVOID GadText(Gad, Str, Len)
  826. Xstruct Gadget *Gad;
  827. Xchar *Str;
  828. XLONG Len;
  829. X{
  830. X    char temp[256];
  831. X    SHORT i;
  832. X
  833. X    SetDrMd(ControlWindow->RPort, JAM2);
  834. X    SetAPen(ControlWindow->RPort, 0L);
  835. X    RectFill(ControlWindow->RPort, (LONG)Gad->LeftEdge, (LONG)Gad->TopEdge,
  836. X      (LONG)Gad->LeftEdge + Gad->Width - 1, (LONG)Gad->TopEdge + Gad->Height - 1);
  837. X    SetAPen(ControlWindow->RPort, 1L);
  838. X    SetBPen(ControlWindow->RPort, 0L);
  839. X    Move(ControlWindow->RPort,
  840. X      (LONG)Gad->LeftEdge + 1,
  841. X      (LONG)Gad->TopEdge + ControlWindow->RPort->Font->tf_Baseline + 1);
  842. X    if (TextLength(ControlWindow->RPort, Str, Len) > Gad->Width) {
  843. X        i = Len;
  844. X        strncpy(temp, Str, i - 3);
  845. X        strcat(temp, "...");
  846. X        while (TextLength(ControlWindow->RPort, temp, (LONG)i) > Gad->Width) {
  847. X            --i;
  848. X            temp[i] = '\0';
  849. X            temp[i-3] = '.';
  850. X        }
  851. X        Text(ControlWindow->RPort, temp, (LONG)i);
  852. X    } else {
  853. X        Text(ControlWindow->RPort, Str, Len);
  854. X    }
  855. X}
  856. X
  857. XVOID SwapColorMap(GS)
  858. Xstruct GfxSnap *GS;
  859. X{
  860. X    struct ViewPort *vp = &GS->window->WScreen->ViewPort;
  861. X    LONG i = (GS->viewmode & HAM ? 16 : 1L << GS->depth);
  862. X    ULONG col;
  863. X
  864. X    while (i-- && (col = GetRGB4(vp->ColorMap, i)) != -1L) {
  865. X        SetRGB4(vp, i,
  866. X          (LONG)GS->rgb[i][0] >> 4,
  867. X          (LONG)GS->rgb[i][1] >> 4,
  868. X          (LONG)GS->rgb[i][2] >> 4);
  869. X        GS->rgb[i][0] = ((col >> 8) & 0x0f) << 4;
  870. X        GS->rgb[i][1] = ((col >> 4) & 0x0f) << 4;
  871. X        GS->rgb[i][2] = ((col >> 0) & 0x0f) << 4;
  872. X    }
  873. X}
  874. X
  875. XVOID CheckWindowMsgs()
  876. X{
  877. X    struct IntuiMessage *Msg;
  878. X    struct IntuiMessage *QdMsg = NULL;
  879. X    ULONG Class;
  880. X    USHORT Code;
  881. X    struct Window *Win;
  882. X    struct Gadget *Gad;
  883. X
  884. X    while (Sharedport &&
  885. X      (QdMsg || (Msg = (struct IntuiMessage *)GetMsg(Sharedport)))) {
  886. X        if (QdMsg) {
  887. X            Msg = QdMsg;
  888. X            QdMsg = NULL;
  889. X        }
  890. X        Class = Msg->Class;
  891. X        Code  = Msg->Code;
  892. X        Win   = Msg->IDCMPWindow;
  893. X        Gad   = (struct Gadget *)Msg->IAddress;
  894. X        ReplyMsg((struct Message *)Msg);
  895. X        switch (Class) {
  896. X            case CLOSEWINDOW: {
  897. X                if (Win == ControlWindow) {
  898. X                    ControlWindow = NULL;
  899. X                    if (SaveWin) {
  900. X                        struct GfxSnap *GS;
  901. X                        SetWindowTitles(SaveWin, WindowTitle, NULL);
  902. X                        GS = (struct GfxSnap *)SaveWin->UserData;
  903. X                        RefreshGList(&GS->DiskGad, GS->window, NULL, 1L);
  904. X                        SaveWin = NULL;
  905. X                    }
  906. X                } else {
  907. X                    struct GfxSnap *GS;
  908. X                    GS = (struct GfxSnap *)Win->UserData;
  909. X                    FreePlanes(&GS->BM, GS->width, GS->height);
  910. X                    Kill(GS);
  911. X                    if (Win == SaveWin) {
  912. X                        if (ControlWindow) {
  913. X                            OffGadget(&SaveGad, ControlWindow, NULL);
  914. X                        }
  915. X                        SaveWin = NULL;
  916. X                    }
  917. X                }
  918. X                closesharedwindow(Win);
  919. X                break;
  920. X            }
  921. X            case NEWSIZE: {
  922. X                AdjustSize((struct GfxSnap *)Win->UserData);
  923. X                break;
  924. X            }
  925. X            case MOUSEMOVE: {
  926. X                  /* Collapse all consecutively queued MOUSEMOVE msgs */
  927. X                while ((QdMsg = (struct IntuiMessage *)GetMsg(Sharedport))
  928. X                  && (QdMsg->Class == MOUSEMOVE)) {
  929. X                    ReplyMsg((struct Message *)QdMsg);
  930. X                }
  931. X                SyncGS((struct GfxSnap *)Win->UserData);
  932. X                break;
  933. X            }
  934. X            case ACTIVEWINDOW: {
  935. X                if (Win != ControlWindow) {
  936. X                    struct GfxSnap *GS;
  937. X                    GS = (struct GfxSnap *)Win->UserData;
  938. X                    RefreshGList(&GS->DiskGad, GS->window, NULL, 1L);
  939. X                }
  940. X                break;
  941. X            }
  942. X            case INACTIVEWINDOW: {
  943. X                if (Win != ControlWindow) {
  944. X                    struct GfxSnap *GS;
  945. X                    if (SwapGS) {
  946. X                        SwapColorMap(SwapGS);
  947. X                        SwapGS = NULL;
  948. X                    }
  949. X                    GS = (struct GfxSnap *)Win->UserData;
  950. X                    RefreshGList(&GS->DiskGad, GS->window, NULL, 1L);
  951. X                }
  952. X                break;
  953. X            }
  954. X            case GADGETUP: {
  955. X                switch (Gad->GadgetID) {
  956. X                    case VPROP:
  957. X                    case HPROP: {
  958. X                        SyncGS((struct GfxSnap *)Win->UserData);
  959. X                        break;
  960. X                    }
  961. X                    case SAVEGAD: {
  962. Xsavepic:
  963. X                        if (SaveWin) {
  964. X                            WORD success;
  965. X                            if (SaveName[0] == '\0') {
  966. X                                DisplayBeep(NULL);
  967. X                                ActivateGadget(&NameGad, ControlWindow, NULL);
  968. X                                break;
  969. X                            }
  970. X                            SnapFile = (BPTR)Open(SaveName, MODE_NEWFILE);
  971. X                            success = SaveGS((struct GfxSnap *)SaveWin->UserData);
  972. X                            Close(SnapFile);
  973. X                            if (success) {
  974. X                                SetWindowTitles(ControlWindow, "Saved ok", NULL);
  975. X                            } else {
  976. X                                DeleteFile(SaveName);
  977. X                                DisplayBeep(NULL);
  978. X                                SetWindowTitles(ControlWindow, "Save failed", NULL);
  979. X                            }
  980. X                        }
  981. X                        break;
  982. X                    }
  983. X                    case NAMEGAD: { /* Should only happen with Arp */
  984. X                        strcpy(SaveDirName, SaveName);
  985. X                        strcpy(SaveName, BaseName(SaveDirName));
  986. X                        *(BaseName(SaveDirName)) = '\0';
  987. X                        NameFR.fr_Window = ControlWindow;
  988. X                        (VOID)FileRequest(&NameFR);
  989. X                        TackOn(SaveDirName, SaveName);
  990. X                        strcpy(SaveName, SaveDirName);
  991. X                        GadText(&NameGad, SaveName, (LONG)strlen(SaveName));
  992. X                        break;
  993. X                    }
  994. X                    case DISKGAD: {
  995. X                        struct GfxSnap *GS;
  996. X                        if (!ControlWindow && !OpenCW()) {
  997. X                            DisplayBeep(NULL);
  998. X                            break;
  999. X                        }
  1000. X                        if (Win == SaveWin) {
  1001. X                            goto savepic;
  1002. X                        }
  1003. X                        if (SaveWin) {
  1004. X                            SetWindowTitles(SaveWin, WindowTitle, NULL);
  1005. X                            GS = (struct GfxSnap *)SaveWin->UserData;
  1006. X                            RefreshGList(&GS->DiskGad, GS->window, NULL, 1L);
  1007. X                        } else {
  1008. X                            GadText(&SaveGad, "Save", 4L);
  1009. X                            OnGadget(&SaveGad, ControlWindow, NULL);
  1010. X                        }
  1011. X                        SaveWin = Win;
  1012. X                        SetWindowTitles(SaveWin, "Selected", NULL);
  1013. X                        GS = (struct GfxSnap *)SaveWin->UserData;
  1014. X                        RefreshGList(&GS->DiskGad, GS->window, NULL, 1L);
  1015. X                        break;
  1016. X                    }
  1017. X                    default: {
  1018. X                        break;
  1019. X                    }
  1020. X                }
  1021. X                break;
  1022. X            }
  1023. X            case MOUSEBUTTONS: {
  1024. X                if (Win != ControlWindow) {
  1025. X                    if (Code == SELECTDOWN && !SwapGS) {
  1026. X                        SwapGS = (struct GfxSnap *)Win->UserData;
  1027. X                        SwapColorMap(SwapGS);
  1028. X                    } else if (Code == SELECTUP && SwapGS) {
  1029. X                        SwapColorMap(SwapGS);
  1030. X                        SwapGS = NULL;
  1031. X                    }
  1032. X                }
  1033. X                break;
  1034. X            }
  1035. X            default: {
  1036. X                break;
  1037. X            }
  1038. X        }
  1039. X    }
  1040. X    if (QdMsg) {
  1041. X        ReplyMsg((struct Message *)QdMsg);
  1042. X    }
  1043. X}
  1044. X
  1045. X#define WriteStdOut(str) Write(StdOut, str, (LONG)strlen(str))
  1046. X
  1047. XVOID main(argc, argv)
  1048. Xint argc;
  1049. Xchar **argv;
  1050. X{
  1051. X    WORD create = 0, usage = 0;
  1052. X
  1053. X    BPTR StdOut = (BPTR)Open("*", MODE_OLDFILE);
  1054. X
  1055. X#ifdef LATTICE
  1056. X    if(_Backstdout)
  1057. X        Close(_Backstdout);
  1058. X
  1059. X    _Backstdout = 0;
  1060. X#endif LATTICE
  1061. X
  1062. X#ifdef AZTEC_C
  1063. X    Enable_Abort = 0;
  1064. X#endif AZTEC_C
  1065. X    if (!(SnapRsrc = (struct SnapRsrc *)OpenResource(SNAPRSRC))) {
  1066. X        create = 1;
  1067. X        SnapRsrc = Create(SnapRsrc);
  1068. X        SnapRsrc->node.ln_Type = NT_RESOURCE;
  1069. X        SnapRsrc->node.ln_Name = SNAPRSRC;
  1070. X        SnapRsrc->Task = FindTask(NULL);
  1071. X        SnapRsrc->Priority = 51;
  1072. X        SnapRsrc->textqual = IEQUALIFIER_LCOMMAND;
  1073. X        SnapRsrc->gfxqual = IEQUALIFIER_RCOMMAND;
  1074. X        SnapRsrc->insertkey = 0x17;
  1075. X        SnapRsrc->cwkey = 0x11;
  1076. X        strcpy(&SnapRsrc->Prepend[0], "> ");
  1077. X        strcpy(&SnapRsrc->Append[0], "");
  1078. X        SnapRsrc->flags = TRUEUNDERSCORE;
  1079. X        SnapRsrc->chardelay = 0;
  1080. X        SnapRsrc->linedelay = 0;
  1081. X        SnapRsrc->CrawlPtrn = 0x7777;
  1082. X        SnapRsrc->StartUnit = UNIT_FRAME;
  1083. X        SnapRsrc->FrameMask = 1;
  1084. X        SnapRsrc->GadOffset = 52;
  1085. X        SnapRsrc->CacheSize = 10;
  1086. X        SnapRsrc->BadChar = '?';
  1087. X        AddResource(SnapRsrc);
  1088. X    }
  1089. X
  1090. X    if (!argc) {    /* WB Startup */
  1091. X        if (!create) {     /* Second time from WB -- Remove Snap */
  1092. X            Signal(SnapRsrc->Task, SIGBREAKF_CTRL_C);
  1093. X            goto exitpoint;
  1094. X        } else {
  1095. X            goto skipargs;
  1096. X        }
  1097. X    }
  1098. X
  1099. X    if (create && StdOut) {
  1100. X        WriteStdOut("Snap 1.4 (c) 1990 Mikael Karlsson\n");
  1101. X    }
  1102. X
  1103. X    for (argc--, argv++; argc > 0; argc--, argv++) {
  1104. X        if (**argv == '-') { /* Argument coming up */
  1105. X            switch(*++(*argv)) {
  1106. X                case 'p': priority: {  /* Priority */
  1107. X                    if (ARGVAL()) {
  1108. X                        WORD pri = dectoint(*argv);
  1109. X                        if (pri>50 && pri<128) {
  1110. X                            SnapRsrc->Priority = pri;
  1111. X                        }
  1112. X                    } else {
  1113. X                        usage = 1;
  1114. X                    }
  1115. X                    break;
  1116. X                }
  1117. X                case 't': textqual: {
  1118. X                    if (ARGVAL()) {
  1119. X                        SnapRsrc->textqual = hextoint(*argv);
  1120. X                    } else {
  1121. X                        usage = 1;
  1122. X                    }
  1123. X                    break;
  1124. X                }
  1125. X                case 'g': gfxqual: {
  1126. X                    if (ARGVAL()) {
  1127. X                        SnapRsrc->gfxqual = hextoint(*argv);
  1128. X                    } else {
  1129. X                        usage = 1;
  1130. X                    }
  1131. X                    break;
  1132. X                }
  1133. X                case 'i': insertkey: {
  1134. X                    if (ARGVAL()) {
  1135. X                        SnapRsrc->insertkey = hextoint(*argv);
  1136. X                    } else {
  1137. X                        usage = 1;
  1138. X                    }
  1139. X                    break;
  1140. X                }
  1141. X                case 'w': cwkey: {
  1142. X                    if (ARGVAL()) {
  1143. X                        SnapRsrc->cwkey = hextoint(*argv);
  1144. X                    } else {
  1145. X                        usage = 1;
  1146. X                    }
  1147. X                    break;
  1148. X                }
  1149. X                case 'c': chardelay: {
  1150. X                    if (ARGVAL()) {
  1151. X                        SnapRsrc->chardelay = dectoint(*argv) * 1000;
  1152. X                    } else {
  1153. X                        usage = 1;
  1154. X                    }
  1155. X                    break;
  1156. X                }
  1157. X                case 'l': linedelay: {
  1158. X                    if (ARGVAL()) {
  1159. X                        SnapRsrc->linedelay = dectoint(*argv) * 1000;
  1160. X                    } else {
  1161. X                        usage = 1;
  1162. X                    }
  1163. X                    break;
  1164. X                }
  1165. X                case 'a': crawlptrn: {
  1166. X                    if (ARGVAL()) {
  1167. X                        SnapRsrc->CrawlPtrn = hextoint(*argv);
  1168. X                    } else {
  1169. X                        usage = 1;
  1170. X                    }
  1171. X                    break;
  1172. X                }
  1173. X                case 'X': noxerox: {
  1174. X                    SnapRsrc->flags &= ~XEROX;
  1175. X                    break;
  1176. X                }
  1177. X                case 'x': xerox: {
  1178. X                    SnapRsrc->flags |= XEROX;
  1179. X                    break;
  1180. X                }
  1181. X                case 'E': noearlypatch: {
  1182. X                    SnapRsrc->flags &= ~EARLYPATCH;
  1183. X                    break;
  1184. X                }
  1185. X                case 'e': earlypatch: {
  1186. X                    SnapRsrc->flags |= EARLYPATCH;
  1187. X                    break;
  1188. X                }
  1189. X                case 'R': fakeunderscore: {
  1190. X                    SnapRsrc->flags &= ~TRUEUNDERSCORE;
  1191. X                    break;
  1192. X                }
  1193. X                case 'r': realunderscore: {
  1194. X                    SnapRsrc->flags |= TRUEUNDERSCORE;
  1195. X                    break;
  1196. X                }
  1197. X                case 'J': nojoinlong: {
  1198. X                    SnapRsrc->flags &= ~JOINLONG;
  1199. X                    break;
  1200. X                }
  1201. X                case 'j': joinlong: {
  1202. X                    SnapRsrc->flags |= JOINLONG;
  1203. X                    break;
  1204. X                }
  1205. X                case 'A': append:
  1206. X                case 'P': prepend: {
  1207. X                    char *dest = (**argv == 'A' ?
  1208. X                      &SnapRsrc->Append[0] : &SnapRsrc->Prepend[0]);
  1209. X                    if (*++(*argv) || (--argc && ++argv)) { /* "" is ok */
  1210. X                        char *src = *argv;
  1211. X                        WORD i = 16;
  1212. X                        while (*src && i--) {
  1213. X                            *dest++ = *src++;
  1214. X                        }
  1215. X                        *dest = '\0';
  1216. X                    } else {
  1217. X                        usage = 1;
  1218. X                    }
  1219. X                    break;
  1220. X                }
  1221. X                case 'u': startunit: {
  1222. X                    if (ARGVAL()) {
  1223. X                        switch(dectoint(*argv)) {
  1224. X                            case 1: {
  1225. X                                SnapRsrc->StartUnit = UNIT_CHAR;
  1226. X                                break;
  1227. X                            }
  1228. X                            case 0:
  1229. X                            default: {
  1230. X                                SnapRsrc->StartUnit = UNIT_FRAME;
  1231. X                                break;
  1232. X                            }
  1233. X                        }
  1234. X                    } else {
  1235. X                        usage = 1;
  1236. X                    }
  1237. X                    break;
  1238. X                }
  1239. X                case 'b': planemask: {
  1240. X                    if (ARGVAL()) {
  1241. X                        SnapRsrc->FrameMask = hextoint(*argv);
  1242. X                    } else {
  1243. X                        usage = 1;
  1244. X                    }
  1245. X                    break;
  1246. X                }
  1247. X                case 'o': gadoffset: {
  1248. X                    if (ARGVAL()) {
  1249. X                        SnapRsrc->GadOffset = dectoint(*argv);
  1250. X                    } else {
  1251. X                        usage = 1;
  1252. X                    }
  1253. X                    break;
  1254. X                }
  1255. X                case 'C': cachesize: {
  1256. X                    if (ARGVAL()) {
  1257. X                        SnapRsrc->CacheSize = dectoint(*argv);
  1258. X                    } else {
  1259. X                        usage = 1;
  1260. X                    }
  1261. X                    break;
  1262. X                }
  1263. X                case 'B': badchar: {
  1264. X                    if (ARGVAL()) {
  1265. X                        SnapRsrc->BadChar = dectoint(*argv);
  1266. X                    } else {
  1267. X                        usage = 1;
  1268. X                    }
  1269. X                    break;
  1270. X                }
  1271. X                case 'Q': quit: {
  1272. X                    Close(StdOut);
  1273. X                    if (create) {
  1274. X                        goto close;
  1275. X                    } else {
  1276. X                        Signal(SnapRsrc->Task, SIGBREAKF_CTRL_C);
  1277. X                        goto exitpoint;
  1278. X                    }
  1279. X                }
  1280. X                case '?': {
  1281. X                    usage = 1;
  1282. X                    break;
  1283. X                }
  1284. X                default: {
  1285. X                    if (StdOut) {
  1286. X                        WriteStdOut("Bad option: -");
  1287. X                        Write(StdOut, *argv, 1L);
  1288. X                        WriteStdOut(".\n");
  1289. X                    }
  1290. X                    usage = 1;
  1291. X                    break;
  1292. X                }
  1293. X            }
  1294. X        } else {
  1295. X            (VOID)strupr(*argv);
  1296. X            if (!strcmp(*argv, "PRIORITY")) {
  1297. X                (*argv)[1] = '\0';                  /* Fake no argument */
  1298. X                goto priority;                      /* Terrible, ain't it? */
  1299. X            } else if (!strcmp(*argv, "TEXTQUAL")) {
  1300. X                (*argv)[1] = '\0';
  1301. X                goto textqual;
  1302. X            } else if (!strcmp(*argv, "GFXQUAL")) {
  1303. X                (*argv)[1] = '\0';
  1304. X                goto gfxqual;
  1305. X            } else if (!strcmp(*argv, "INSERTKEY")) {
  1306. X                (*argv)[1] = '\0';
  1307. X                goto insertkey;
  1308. X            } else if (!strcmp(*argv, "CWKEY")) {
  1309. X                (*argv)[1] = '\0';
  1310. X                goto cwkey;
  1311. X            } else if (!strcmp(*argv, "PREPEND")) {
  1312. X                (*argv)[1] = '\0';
  1313. X                goto prepend;
  1314. X            } else if (!strcmp(*argv, "APPEND")) {
  1315. X                (*argv)[1] = '\0';
  1316. X                goto append;
  1317. X            } else if (!strcmp(*argv, "CHARDELAY")) {
  1318. X                (*argv)[1] = '\0';
  1319. X                goto chardelay;
  1320. X            } else if (!strcmp(*argv, "LINEDELAY")) {
  1321. X                (*argv)[1] = '\0';
  1322. X                goto linedelay;
  1323. X            } else if (!strcmp(*argv, "CRAWLPTRN")) {
  1324. X                (*argv)[1] = '\0';
  1325. X                goto crawlptrn;
  1326. X            } else if (!strcmp(*argv, "XEROX")) {
  1327. X                goto xerox;
  1328. X            } else if (!strcmp(*argv, "NOXEROX")) {
  1329. X                goto noxerox;
  1330. X            } else if (!strcmp(*argv, "EARLYPATCH")) {
  1331. X                goto earlypatch;
  1332. X            } else if (!strcmp(*argv, "NOEARLYPATCH")) {
  1333. X                goto noearlypatch;
  1334. X            } else if (!strcmp(*argv, "TRUEUNDERSCORE")) {
  1335. X                goto realunderscore;
  1336. X            } else if (!strcmp(*argv, "FAKEUNDERSCORE")) {
  1337. X                goto fakeunderscore;
  1338. X            } else if (!strcmp(*argv, "JOINLONG")) {
  1339. X                goto joinlong;
  1340. X            } else if (!strcmp(*argv, "NOJOINLONG")) {
  1341. X                goto nojoinlong;
  1342. X            } else if (!strcmp(*argv, "STARTUNIT")) {
  1343. X                (*argv)[1] = '\0';
  1344. X                goto startunit;
  1345. X            } else if (!strcmp(*argv, "PLANEMASK")) {
  1346. X                (*argv)[1] = '\0';
  1347. X                goto planemask;
  1348. X            } else if (!strcmp(*argv, "GADOFFSET")) {
  1349. X                (*argv)[1] = '\0';
  1350. X                goto gadoffset;
  1351. X            } else if (!strcmp(*argv, "CACHESIZE")) {
  1352. X                (*argv)[1] = '\0';
  1353. X                goto cachesize;
  1354. X            } else if (!strcmp(*argv, "BADCHAR")) {
  1355. X                (*argv)[1] = '\0';
  1356. X                goto badchar;
  1357. X            } else if (!strcmp(*argv, "QUIT")) {
  1358. X                goto quit;
  1359. X            } else if (strcmp(*argv, "?") && StdOut) {
  1360. X                WriteStdOut("Bad switch/keyword: ");
  1361. X                WriteStdOut(*argv);
  1362. X                WriteStdOut(".\n");
  1363. X            }
  1364. X            usage = 1;
  1365. X        }
  1366. X    }
  1367. X
  1368. X    if (usage && StdOut) {
  1369. X        WriteStdOut("Usage:\n");
  1370. X        WriteStdOut(" snap -pNN -tXX -gXX -iXX -wXX -Pstr -Astr -cNN -lNN -aXXXX\n");
  1371. X        WriteStdOut("   -x -X -e -E -uN -r -R -j -J -bXX -oNN -CNN -BNN -Q\n");
  1372. X        WriteStdOut(" or\n");
  1373. X        WriteStdOut(" snap PRIORITY/k TEXTQUAL/k GFXQUAL/k INSERTKEY/k CWKEY/k\n");
  1374. X        WriteStdOut("   PREPEND/k APPEND/k CHARDELAY/k LINEDELAY/k CRAWLPTRN/k\n");
  1375. X        WriteStdOut("   XEROX/s NOXEROX/s EARLYPATCH/s NOEARLYPATCH/s STARTUNIT/k\n");
  1376. X        WriteStdOut("   TRUEUNDERSCORE/s FAKEUNDERSCORE/s JOINLONG/s NOJOINLONG/s\n");
  1377. X        WriteStdOut("   PLANEMASK/k GADOFFSET/k CACHESIZE/k BADCHAR/s QUIT/s\n");
  1378. X    }
  1379. X
  1380. Xskipargs:
  1381. X    if (StdOut) {
  1382. X        Close(StdOut);
  1383. X    }
  1384. X
  1385. X    if (!create) {
  1386. X          /* Tell him there are new settings available */
  1387. X        Signal(SnapRsrc->Task, SIGBREAKF_CTRL_F);
  1388. X        goto exitpoint;
  1389. X    }
  1390. X
  1391. X    textqual = SnapRsrc->textqual;
  1392. X    gfxqual = SnapRsrc->gfxqual;
  1393. X    insertkey = SnapRsrc->insertkey;
  1394. X    cwkey = SnapRsrc->cwkey;
  1395. X    TrueUnderscore = SnapRsrc->flags & TRUEUNDERSCORE ? 1 : 0;
  1396. X
  1397. X    if (!OpenStuff()) {
  1398. X        goto close;
  1399. X    }
  1400. X
  1401. X#ifdef SNAPREXX
  1402. X    rexxsignal = upRexxPort("SNAP", &rcl, NULL, &disp);
  1403. X#endif
  1404. X
  1405. X    /* This is what we're waiting for */
  1406. X    WaitSignal = startsignal | insertsignal | initsignal | cancelsignal |
  1407. X#ifdef SNAPREXX
  1408. X                 rexxsignal |
  1409. X#endif
  1410. X                 cwsignal | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F;
  1411. X
  1412. X    FOREVER {
  1413. X        REGISTER LONGBITS sig =
  1414. X          Wait(WaitSignal |
  1415. X               (Sharedport ? (1L << Sharedport->mp_SigBit) : 0L));
  1416. X        CheckWindowMsgs();
  1417. X#ifdef SNAPREXX
  1418. X        if (sig & rexxsignal) {
  1419. X            dispRexxPort();
  1420. X        }
  1421. X#endif
  1422. X        if (sig & SIGBREAKF_CTRL_C) {
  1423. X            /* This is my cue. Exit if there are no open windows depending on us */
  1424. X            if (Sharedrefs) {
  1425. X                DisplayBeep(NULL);
  1426. X            } else {
  1427. X                goto close;
  1428. X            }
  1429. X        }
  1430. X        if (sig & SIGBREAKF_CTRL_F) {
  1431. X            /* Hey, seems like there are new settings available. */
  1432. X            textqual = SnapRsrc->textqual;
  1433. X            gfxqual = SnapRsrc->gfxqual;
  1434. X            insertkey = SnapRsrc->insertkey;
  1435. X            cwkey = SnapRsrc->cwkey;
  1436. X            TrueUnderscore = SnapRsrc->flags & TRUEUNDERSCORE ? 1 : 0;
  1437. X        }
  1438. X        if (sig & initsignal) {
  1439. X            if (SnapRsrc->flags & (XEROX | EARLYPATCH)) {
  1440. X                SafePatch();               /* Patch dangerous functions */
  1441. X            }
  1442. X        }
  1443. X        if (sig & cancelsignal) {
  1444. X            SafeRestore();
  1445. X        }
  1446. X        if (sig & startsignal) { /* The handler wants a word in. */
  1447. X            SafePatch();
  1448. X            if (action == snapgfx) {       /* Check user action */
  1449. X                HandleGfx();               /* Get the picture :-) */
  1450. X            } else if (action == snaptext) {
  1451. X                if (HandleChars()) {             /* Snap some chars */
  1452. X                    if (SnapRsrc->flags & XEROX) {
  1453. X                        sig |= insertsignal;
  1454. X                    }
  1455. X                }
  1456. X            } else {
  1457. X                  /* Previous snap wasn't finished when this one started. */
  1458. X                SetSignal(0L,
  1459. X                  movesignal|cancelsignal|donesignal|clicksignal|timersignal);
  1460. X                DisplayBeep(NULL);
  1461. X                action = noaction;
  1462. X            }
  1463. X            if (!(sig & insertsignal)) {
  1464. X                SafeRestore();             /* Layers unlocked - all safe */
  1465. X            }
  1466. X        }
  1467. X
  1468. X        if (sig & insertsignal) {
  1469. X            LONG i;
  1470. X            struct Snap *Snap;
  1471. X            ULONG ascii;
  1472. X
  1473. X            action = insert;
  1474. X            if (Snap = FetchClip()) {  /* Get clipboard data */
  1475. X                  /* get the current keymap  */
  1476. X                ConIOR->io_Command =  CD_ASKDEFAULTKEYMAP;
  1477. X                ConIOR->io_Length  = sizeof (struct KeyMap);
  1478. X                ConIOR->io_Data    = (APTR) &keymap;
  1479. X                ConIOR->io_Flags   = 1;    /* no IOQuick   */
  1480. X                DoIO(ConIOR);
  1481. X                  /* Set up an input request */
  1482. X                inputRequestBlock->io_Command = IND_WRITEEVENT;
  1483. X                inputRequestBlock->io_Flags   = 0L;
  1484. X                inputRequestBlock->io_Length  = (long)sizeof(struct InputEvent);
  1485. X                inputRequestBlock->io_Data    = (APTR)&SimEvent;
  1486. X                  /* Translate chars in SnapSpace and insert them
  1487. X                     into the input stream. */
  1488. X                insertcount = 0;
  1489. X                ascii = 13;  /* Simulate start of new line */
  1490. X                for (i = 0; Snap->Chars[i] && (action == insert); ++i) {
  1491. X                    if (ascii == 13 && modinsert) {
  1492. X                        int cnt = 0;
  1493. X                        while (ascii = SnapRsrc->Prepend[cnt++]) {
  1494. X                            InsertAscii(ascii);
  1495. X                        }
  1496. X                    }
  1497. X
  1498. X                    ascii = Snap->Chars[i];
  1499. X                    if (ascii == 10) {
  1500. X                        if (modinsert) {
  1501. X                            int cnt = 0;
  1502. X                            while (ascii = SnapRsrc->Append[cnt++]) {
  1503. X                                InsertAscii(ascii);
  1504. X                            }
  1505. X                        }
  1506. X                        ascii = 13;     /* WYSIWYG? Hah! */
  1507. X                        if (SnapRsrc->linedelay) {
  1508. X                            MyTR.tr_node.io_Command = TR_ADDREQUEST;
  1509. X                            MyTR.tr_time.tv_micro = SnapRsrc->linedelay;
  1510. X                            MyTR.tr_time.tv_secs = 0;
  1511. X                            DoIO((struct IOStdReq *)&MyTR);
  1512. X                        }
  1513. X                    }
  1514. X                    InsertAscii(ascii);
  1515. X                }
  1516. X                if (modinsert) {
  1517. X                    int cnt = 0;
  1518. X                    while (ascii = SnapRsrc->Append[cnt++]) {
  1519. X                        InsertAscii(ascii);
  1520. X                    }
  1521. X                }
  1522. X                SafeRestore();  /* "Depatch" */
  1523. X                  /* Free memory given to us by FetchClip() */
  1524. X                FreeMem(Snap, Snap->Size);
  1525. X            }
  1526. X            action = noaction;
  1527. X            modinsert = 0;
  1528. X        }
  1529. X
  1530. X        if (sig & cwsignal) {
  1531. X            if (!ControlWindow && !OpenCW()) {
  1532. X                DisplayBeep(NULL);
  1533. X            }
  1534. X        }
  1535. X    }
  1536. X
  1537. Xclose:
  1538. X#ifdef SNAPREXX
  1539. X    dnRexxPort();
  1540. X#endif
  1541. X    CloseStuff();  /* Guess what */
  1542. Xexitpoint: ;
  1543. X}
  1544. X
  1545. END_OF_FILE
  1546. if test 29507 -ne `wc -c <'source/snap.c'`; then
  1547.     echo shar: \"'source/snap.c'\" unpacked with wrong size!
  1548. fi
  1549. # end of 'source/snap.c'
  1550. fi
  1551. echo shar: End of archive 4 \(of 4\).
  1552. cp /dev/null ark4isdone
  1553. MISSING=""
  1554. for I in 1 2 3 4 ; do
  1555.     if test ! -f ark${I}isdone ; then
  1556.     MISSING="${MISSING} ${I}"
  1557.     fi
  1558. done
  1559. if test "${MISSING}" = "" ; then
  1560.     echo You have unpacked all 4 archives.
  1561.     rm -f ark[1-9]isdone
  1562. else
  1563.     echo You still need to unpack the following archives:
  1564.     echo "        " ${MISSING}
  1565. fi
  1566. ##  End of shell archive.
  1567. exit 0
  1568. -- 
  1569. Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
  1570. Mail comments to the moderator at <amiga-request@cs.odu.edu>.
  1571. Post requests for sources, and general dicussion to comp.sys.amiga.
  1572.